Skip to content

Conversation

@ibc
Copy link
Member

@ibc ibc commented Mar 20, 2025

Details

  • This PR basically reverts PR Export EM and CJS bundle files #32 because this is hell. More about this in Why??? section below.
  • Only generate CommonJS code in lib/ instead of both ESM and CommonJS code.
  • Remove Babel stuff and rely on tsc to generate CommonJS code and TypeScript declaration files in lib/.

Why???

  • Because this is hell. Totally hell.
  • Before this PR, rtp.js can not be used in TypeScript projects that use Webpack to generate a bundled JS file. Why? Because Webpack assumes that everything is CommonJS but then it miserably fails to locate/resolve '.cjs' files.
  • If we have '.ts' files in src/ folder, then tsc will generate 'js' files rather than '.mjs' files, and that means problems with loaders/bundlers that assume that '.js' files contain CommonJS and then they fail to process them because those '.js' files contain 'import/export' rather than 'require/module.exports'.
  • And if we have '.mts' files in src then tsc will generate .mjs with ESM code but it's literally impossible to have another tsconfig-cjs.json file to make tsc generate CommonJS code with ".js" or ".cjs" extension.
  • So then we moved to Babel to generate ESM and CJS code (see PR Export EM and CJS bundle files #32), and we have to include tricks to replace the extension in the import and require() calls in the generated ESM and CJS code in lib/, which is terrible. But then Babel also generates .js.map files that reference a .mts file in lib/ folder which obviously doesn't exist.
  • And another problem is that Babel only generates JavaScript code so we still need to use tsc to generate TypeScript declaration files and, since we have '.mts' files in src/, those declaration files have d.mts extension. But they many text editors and TypeScript consumers asusme that declaraion files must be '.d.ts' only. And if we rename their extension then we have also to munge generated .mjs (ESM) and .cjs files in lib/ because those files contain special commented mapping lines that reference the declaration file (with '.d.mts').
  • And then it also happens that in CommonJS importing a file without extendion is ok, but in ESM you must write import foo from './foo.ts' rather than from './foo'. So here another needed rewrite in generated lib/ code.
  • etc etc etc, and trust me, more etc etc etc. I've tried EVERYTHING, much more than what I've told here.

Conclusion

  • It's impossible to generate ESM and CJS file in a proper way because it entirely affects the way the TypeScript code must be written, and it includes whether to use .ts or .mts extension in source files, whether to import internal files with or without extension, and tsconfig.json doesn't expose options enough to cover all cases we need when generating ESM or CJS code. I've checked them all, and the same with Babel.
  • My conclusion is that, if you want to publish a library in ESM format, you only generate ESM code ('.mjs' files) from TypeScript '.mts' files. But you cannot generate also CJS files. And the other way around.

## Details

- This PR basically reverts PR #32 because this is hell. More about this in **Why???** section below.
- Only generate CommonJS code in `lib/` instead of both ESM and CommonJS code.
- Remove Babel stuff and rely on `tsc` to generate CommonJS code and TypeScript declaration files in `lib/`.

## Why???

- Because this is hell. Totally hell.
- Before this PR, rtp.js can not be used in TypeScript projects that use Webpack to generate a bundled JS file. Why? Because Webpack assumes that everything is CommonJS but then it miserably fails to locate/resolve '.cjs' files.
- If we have '.ts' files in `src/` folder, then `tsc` will generate 'js' files rather than '.mjs' files, and that means problems with loaders/bundlers that assume that '.js' files contain CommonJS and then they fail to process them because those '.js'  files contain 'import/export' rather than 'require/module.exports'.
- And if we have '.mts' files in `src` then `tsc` will generate `.mjs` with ESM code but it's literally impossible to have another `tsconfig-cjs.json` file to make `tsc` generate CommonJS code.
- So then we moved to Babel to generate ESM and CJS code (see PR #32), and we have to include tricks to replace the extension in the `import` and `require()` calls in the generated ESM and CJS code in `lib/`, which is terrible. But then Babel also generates `.js.map` files that reference a `.mts` file in `lib/` folder which obviously doesn't exist.
- And another problem is that Babel only generates JavaScript code so we still need to use `tsc` to generate TypeScript declaration files and, since we have '.mts' files in `src/`, those declaration files have `d.mts` extension. But they many text editors and TypeScript consumers asusme that declaraion files must be '.d.ts' only. And if we rename their extension then we have also to munge generated `.mjs` (ESM) and `.cjs` files in `lib/` because those files contain special commented mapping lines that reference the declaration file (with '.d.mts').
- And then it also happens that in CommonJS importing a file without extendion is ok, but in ESM you must write `import foo from './foo.ts'` rather than `from './foo'`. So here another needed rewrite in generated `lib/` code.
- etc etc etc, and **trust me**, more etc etc etc. I've tried EVERYTHING, much more than what I've told here.

## Conclusion

- It's impossible to generate ESM and CJS file in a proper way because it entirely affects the way the TypeScript code must be written, and it includes whether to use `.ts` or `.mts` extension in source files, whether to import internal files with or without extension, and `tsconfig.json` doesn't expose options enough to cover all cases we need when generating ESM or CJS code. I've checked them all, and the same with Babel.
- My conclusion is that, if you want to publish a library in ESM format, you only generate ESM code ('.mjs' files) from TypeScript '.mts' files. But you cannot generate **also** CJS files. And the other way around.
@ibc ibc merged commit d106a78 into master Mar 20, 2025
8 checks passed
@ibc ibc deleted the redo-esm-cjs-stuff branch March 20, 2025 15:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants